import random
import time
import math
import win32api
import win32con

def cubic_bezier(p0, p1, p2, p3, num_points):
    """生成三次贝塞尔曲线点"""
    points = []
    for t in (i / (num_points - 1) for i in range(num_points)):
        x = (1 - t)**3 * p0[0] + 3 * (1 - t)**2 * t * p1[0] + 3 * (1 - t) * t**2 * p2[0] + t**3 * p3[0]
        y = (1 - t)**3 * p0[1] + 3 * (1 - t)**2 * t * p1[1] + 3 * (1 - t) * t**2 * p2[1] + t**3 * p3[1]
        points.append((x, y))
    return points

def generate_control_points(start, end, screen_w, screen_h):
    """生成带边界约束的控制点"""
    dx = end[0] - start[0]
    dy = end[1] - start[1]
    
    perp_dx = -dy
    perp_dy = dx
    
    length = math.hypot(perp_dx, perp_dy)
    if length == 0:
        return (start, start, end, end)
    
    perp_dx /= length
    perp_dy /= length
    
    max_intensity = min(screen_w, screen_h) * 0.15
    curve_intensity = math.hypot(dx, dy) * random.uniform(0.1, 0.3)
    curve_intensity = min(curve_intensity, max_intensity)
    
    def clamp(value, min_val, max_val):
        return max(min_val, min(value, max_val))
    
    ctrl1 = (
        clamp(start[0] + dx * 0.25 + perp_dx * curve_intensity, 0, screen_w),
        clamp(start[1] + dy * 0.25 + perp_dy * curve_intensity, 0, screen_h)
    )
    ctrl2 = (
        clamp(start[0] + dx * 0.75 - perp_dx * curve_intensity, 0, screen_w),
        clamp(start[1] + dy * 0.75 - perp_dy * curve_intensity, 0, screen_h)
    )
    return ctrl1, ctrl2

def human_mouse_move(end_x, end_y, duration=0.5, num_points=200):
    """改进版鼠标移动核心函数"""
    screen_w = win32api.GetSystemMetrics(0) - 1
    screen_h = win32api.GetSystemMetrics(1) - 1
    
    try:
        start_x, start_y = win32api.GetCursorPos()
    except win32api.error:
        raise Exception("无法获取初始鼠标位置")
    
    end_x = max(0, min(end_x, screen_w))
    end_y = max(0, min(end_y, screen_h))
    
    start = (start_x, start_y)
    end = (end_x, end_y)
    ctrl1, ctrl2 = generate_control_points(start, end, screen_w, screen_h)
    
    points = cubic_bezier(start, ctrl1, ctrl2, end, num_points)
    
    points = [
        (
            x + random.uniform(-0.5, 0.5),
            y + random.uniform(-0.5, 0.5)
        ) for x, y in points
    ]
    
    points = [
        (max(0, min(x, screen_w)), 
        max(0, min(y, screen_h)))
        for x, y in points
    ]
    
    base_delay = duration / len(points)
    
    for i, (target_x, target_y) in enumerate(points):
        try:
            current_x, current_y = win32api.GetCursorPos()
        except win32api.error:
            break
        
        dx = target_x - current_x
        dy = target_y - current_y
        
        if i == len(points) - 1:
            dx = end_x - current_x
            dy = end_y - current_y
        
        new_x = current_x + dx
        new_y = current_y + dy
        actual_dx = dx
        actual_dy = dy
        
        if new_x < 0:
            actual_dx = -current_x
        elif new_x > screen_w:
            actual_dx = screen_w - current_x
        
        if new_y < 0:
            actual_dy = -current_y
        elif new_y > screen_h:
            actual_dy = screen_h - current_y
        
        if actual_dx != 0 or actual_dy != 0:
            win32api.mouse_event(
                win32con.MOUSEEVENTF_MOVE,
                int(round(actual_dx)),
                int(round(actual_dy)),
                0,
                0
            )
        
        time.sleep(base_delay * random.uniform(0.7, 1.3))
    
    # 最终位置校正
    current_x, current_y = win32api.GetCursorPos()
    if (current_x, current_y) != (end_x, end_y):
        dx = end_x - current_x
        dy = end_y - current_y
        for _ in range(3):
            if dx == 0 and dy == 0:
                break
            win32api.mouse_event(
                win32con.MOUSEEVENTF_MOVE,
                int(dx),
                int(dy),
                0,
                0
            )
            time.sleep(0.01)
            current_x, current_y = win32api.GetCursorPos()
            dx = end_x - current_x
            dy = end_y - current_y

def get_valid_coordinate(prompt, max_value):
    """获取有效坐标输入"""
    while True:
        try:
            value = int(input(prompt))
            if 0 <= value <= max_value:
                return value
            print(f"输入超出范围 (0-{max_value})，请重新输入")
        except ValueError:
            print("请输入有效的整数")

if __name__ == "__main__":
    # 获取屏幕尺寸
    screen_w = win32api.GetSystemMetrics(0) - 1
    screen_h = win32api.GetSystemMetrics(1) - 1
    
    print(f"当前屏幕尺寸：{screen_w}x{screen_h}")
    print("请输入目标坐标：")
    
    # 获取有效输入
    target_x = 100
    target_y = 200
    
    # 执行移动
    try:
        print(f"开始移动到 ({target_x}, {target_y})")
        human_mouse_move(target_x, target_y)
        final_pos = win32api.GetCursorPos()
        print(f"移动完成，最终位置: {final_pos}")
    except Exception as e:
        print(f"移动过程中出现错误: {str(e)}")